/**
 * 路由守卫 - 处理路由权限验证和页面加载状态
 */

import type { RouteLocationNormalized, Router } from 'vue-router'
import * as NProgress from 'nprogress'
import 'nprogress/nprogress.css'

import { accessRoutes, coreRouteNames } from './routes'
import { fallbackNotFound } from './routes/core'
import { generateRoute } from '@/helpers/generateRoute'
import { useAccessStore } from '@/stores/modules/access'
import { useLoadingStore } from '@/stores/modules/loading'
import { convertToVueRoutes, needsPermissionCheck } from '@/utils/router'
import { LOGIN_PATH } from '@/constants/router'
import type { BaseRoute } from '@/types/router'
import { STORAGE_LOGIN_TOKEN } from '@/constants/localKey'

// 路由生成状态
let isRoutesGenerated = false

// 获取token
const getToken = () => {
    return localStorage.getItem(STORAGE_LOGIN_TOKEN) || sessionStorage.getItem(STORAGE_LOGIN_TOKEN)
}

/**
 * 通用路由守卫 - 处理页面加载进度条和页面切换加载
 * @param router 路由实例
 */
const setupCommonGuard = (router: Router): void => {
    const loadedPaths = new Set<string>()

    router.beforeEach(async (to, from) => {
        const isPageSwitch = from.name && to.name !== from.name
        const isFirstLoad = !loadedPaths.has(to.path)
        const loadingStore = useLoadingStore() // 提前获取store

        to.meta.loaded = loadedPaths.has(to.path)

        // 页面切换且首次加载：开始加载
        if (isPageSwitch && isFirstLoad) {
            const routeTitle = (to.meta.title as string) || '页面'
            loadingStore.startPageLoading(`正在加载${routeTitle}...`)
        }

        if (!to.meta.loaded) {
            NProgress.start()
        }
        return true
    })

    router.afterEach(async (to) => {
        loadedPaths.add(to.path)
        NProgress.done()

        // 等待所有请求完成后再隐藏页面加载
        const loadingStore = useLoadingStore()
        if (loadingStore.isPageLoading) {
            try {
                // 给一个短暂的延迟，确保组件mounted后的请求能被正确计数
                await new Promise((resolve) => setTimeout(resolve, 200))

                // 如果此时还没有请求在进行，再等待一小段时间确保请求开始
                if (loadingStore.pendingRequests === 0) {
                    await new Promise((resolve) => setTimeout(resolve, 100))
                }

                await loadingStore.waitForAllRequests()
            } finally {
                console.log('结束页面加载')
                loadingStore.endPageLoading()
            }
        }
    })
}

/**
 * 权限路由守卫 - 处理登录验证和动态路由生成
 * @param router 路由实例
 */
const setupPermissionGuard = (router: Router): void => {
    router.beforeEach(async (to) => {
        // 核心路由，无需权限验证
        if (!needsPermissionCheck(to.name as string, coreRouteNames as string[])) {
            // 如果已登录且访问登录页，重定向到首页或指定页面
            if (to.path === LOGIN_PATH && getToken()) {
                return decodeURIComponent((to.query.redirect as string) || '/')
            }
            return true
        }

        // 权限路由，需要登录验证
        if (!getToken()) {
            return handleUnauthorizedAccess(to)
        }

        // 生成动态路由（仅首次）
        try {
            if (!isRoutesGenerated) {
                await generateDynamicRoutes(router)
                isRoutesGenerated = true
                return { ...to, replace: true }
            }
            return true
        } catch (error) {
            console.error('路由初始化失败:', error)
            try {
                const accessStore = useAccessStore()
                accessStore.reset()
                sessionStorage.removeItem(STORAGE_LOGIN_TOKEN)
            } catch (err) {
                void err
            }
            isRoutesGenerated = false
            return { path: LOGIN_PATH, replace: true }
        }
    })
}

/**
 * 处理未授权访问
 * @param to 目标路由
 * @returns 重定向到登录页
 */
const handleUnauthorizedAccess = (to: RouteLocationNormalized) => {
    if (to.path !== LOGIN_PATH) {
        return {
            path: LOGIN_PATH,
            query: to.fullPath === '/' ? {} : { redirect: encodeURIComponent(to.fullPath) },
            replace: true,
        }
    }
    return to
}

/**
 * 生成动态路由
 * @param router 路由实例
 */
const generateDynamicRoutes = async (router: Router): Promise<void> => {
    const accessStore = useAccessStore()

    // 获取路由数据
    const routeData = await accessStore.initRoutes()

    // 转换为 Vue Router 格式
    const dynamicRoutes = convertToVueRoutes([...routeData, ...accessRoutes] as BaseRoute[])

    // 生成路由
    generateRoute({
        router,
        accessRoutes: [...dynamicRoutes],
    })
    // 注册成功之后将accessRoutes赋值给accessStore.accessMenu
    accessStore.setAccessMenu([...routeData, ...accessRoutes] as BaseRoute[])

    // 添加 404 路由
    router.addRoute(fallbackNotFound)
}

/**
 * 重置路由状态（用于登出等场景）
 */
export const resetRouterState = (): void => {
    isRoutesGenerated = false
}

/**
 * 创建路由守卫
 * @param router 路由实例
 */
export const createRouterGuard = (router: Router): void => {
    setupCommonGuard(router)
    setupPermissionGuard(router)
}
